Given a string s and an integer k, return true if s is a k-palindrome.
A string is k-palindrome if it can be transformed into a palindrome by removing at most k characters from it.
Example 1:
Input: s = "abcdeca", k = 2 Output: true Explanation: Remove 'b' and 'e' characters.
Example 2:
Input: s = "abbababa", k = 1 Output: true
Constraints:
1 <= s.length <= 1000sconsists of only lowercase English letters.1 <= k <= s.length
Average Rating: 5.00 (10 votes)
Solution
Approach 1: Top-Down DP (2D)
Intuition
Let's try to find the minimum number of character that can be removed to make the string a palindrome. If we see that the minimum number is less than or equal to k we can conclude that it is indeed a K-Palindrome, else it is not.
Similar Problems:
Algorithm
How do we find the minimum characters to be removed to make it a palindrome?
Let's imagine matching the characters of the string like a palindrome, from the beginning and the end with 2 pointers i and j.
We may encounter the following two scenarios:
- The character at
imatches character atj. - The characters don't match each other.
For case 1 we just increase the pointer i and decrease the pointer j, i++ and j-- respectively.
In the second case we have 2 options:
- Remove character at
jand see if the previous character matches character ati.
Or
- Remove character at
iand see if the next character matches character atj.
Since we are not actually removing the characters from the string but just calculating the number of characters to be removed,
in case 1 we decrement the pointer j by 1 and i stays as it is, as we still need a character to match character at i
and in case 2 we increment the pointer i by 1 and j stays as it is, as we still need a character to match character at j.
In both the cases we remove 1 character and thus it adds 1 to the cost.
We can then use these two different pairs of new i and j values (i+1, j and i, j-1) to again repeat the process and get the minimum result of them as our result for current pair i, j.
We can see that this is recursive and thus we can use recursion with caching to store the repeated values.
Complexity Analysis
-
Time complexity : O(n2). Where
nis the length of strings. This is due to the fact that we try to find result for all combinations ofiandjwhereiandjrange from0ton, to compute a combination we perform an O(1) operation thus the final complexity is O(n2). -
Space complexity : O(n2). Where
nis the length of strings. This is due to caching all the results inmemotable. The recursion stack depth can reach at max O(n) depth. Thus the complexity is dominated by the space required formemo.
Approach 2: Bottom-Up DP (2D)
Algorithm
Instead of filing up our memo table from top to bottom, let's try filling it from bottom to top. All we need to do is fill all the combinations of i and j in the correct order so that we have all the results required for the next state (combination of i, j) before we move to the next state (combination of i, j).
Complexity Analysis
-
Time complexity : O(n2). Where
nis the length of strings. This is due to the fact that we try to find result for all combinations ofiandjwhereiandjrange from0ton, to compute a combination we perform an O(1) operation thus the final complexity is O(n2). -
Space complexity : O(n2). Where
nis the length of strings. This is due to thememotable which is completely filled in this case.
Approach 3: Bottom-Up DP (1D)
Algorithm
On looking closely to both the approaches mentioned above you'll notice that for any combination of i and j, you essentially only need the i+1'th row and j-1'th column. Thus we know we can reduce the space complexity to only O(n) from O(n2).
An efficient way of doing so is using the previous contained value in the memo which represents result for the previous state before storing the result for current state. This is better than the approach of managing two arrays (previous and current) and copying them after every calculation.
Complexity Analysis
-
Time complexity : O(n2). Where
nis the length of strings. This is due to the fact that we try to find result for all combinations ofiandjwhereiandjrange from0ton, to compute a combination we perform an O(1) operation thus the final complexity is O(n2). -
Space complexity : O(n). Where
nis the length of strings. This is due to thememotable which stores result for only one row/iand all it's combination columns/j.
very clear,thank you. I think it is one of the best solution in leetcode.
June 5, 2021 5:40 PM
brilliant solution. thank you!
what is the thinking process/mindset/intuition of working out the correct order for combinations of (i, j) ? I was quite struggling on that.
You don't have any submissions yet.
xxxxxxxxxxclass Solution {public: bool isValidPalindrome(string s, int k) { }};